package com.easylinkin.linkappapi.lobar.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.aliyun.ocr_api20210707.Client;
import com.aliyun.ocr_api20210707.models.RecognizeIdcardRequest;
import com.aliyun.ocr_api20210707.models.RecognizeIdcardResponse;
import com.aliyun.tea.TeaException;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.common.model.RequestModel;
import com.easylinkin.linkappapi.lobar.dto.CheckPeopleInfoDTO;
import com.easylinkin.linkappapi.lobar.dto.CheckRecordDTO;
import com.easylinkin.linkappapi.lobar.dto.OCRIdentifyDTO;
import com.easylinkin.linkappapi.lobar.entity.AppPeopleCheck;
import com.easylinkin.linkappapi.lobar.entity.WarningConfig;
import com.easylinkin.linkappapi.lobar.entity.vo.*;
import com.easylinkin.linkappapi.lobar.mapper.LaborManagementMapper;
import com.easylinkin.linkappapi.lobar.mapper.WarningConfigMapper;
import com.easylinkin.linkappapi.lobar.service.LaborManagementService;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import site.morn.rest.RestBuilders;
import site.morn.rest.RestMessage;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.*;

@Service
public class LaborManagementServiceImpl extends ServiceImpl<LaborManagementMapper, AppPeopleCheck> implements LaborManagementService {

    @Resource
    private LinkappUserContextProducer linkappUserContextProducer;
    @Autowired
    private LaborManagementMapper laborManagementMapper;
    @Autowired
    private WarningConfigMapper warningConfigMapper;

    @Value("${aliocr.accesskeyid}")
    private String accessKeyId;

    @Value("${aliocr.accesskeysecret}")
    private String accessKeySecret;

    @Value("${aliocr.endpoint}")
    private String endpoint;

    @Override
    public RestMessage getPeopleInfo(CheckPeopleInfoDTO query) {
        LinkappUser currentUser = linkappUserContextProducer.getCurrent();
        if ("null".equals(query.getCardNo())) {
            // 未登记
            PeopleInfoVo info = new PeopleInfoVo();
            CheckRecordInfoVo checkRecordInfoVo = new CheckRecordInfoVo();
            checkRecordInfoVo.setRecordPeople(currentUser.getNickname());
            checkRecordInfoVo.setCheckTime(new Date());
            RecordDetailVo recordDetailVo = new RecordDetailVo();
            recordDetailVo.setPeopleInfoVo(info);
            recordDetailVo.setCheckRecordInfoVo(checkRecordInfoVo);
            return RestBuilders.successBuilder().data(recordDetailVo).build();
        }

        //项目id 过滤
        if (null != currentUser) {
            query.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        }
        // 查询核查人员信息
        PeopleInfoVo peopleInfo = laborManagementMapper.getPeopleInfo(query);
        String checkIn;
        // 未登记
        if (peopleInfo == null) {
            // 未登记
            PeopleInfoVo info = new PeopleInfoVo();
            info.setCardNo(query.getCardNo());
            CheckRecordInfoVo checkRecordInfoVo = new CheckRecordInfoVo();
            checkRecordInfoVo.setRecordPeople(currentUser.getNickname());
            checkRecordInfoVo.setCheckTime(new Date());
            RecordDetailVo recordDetailVo = new RecordDetailVo();
            recordDetailVo.setPeopleInfoVo(info);
            recordDetailVo.setCheckRecordInfoVo(checkRecordInfoVo);
            return RestBuilders.successBuilder().data(recordDetailVo).build();
        }
        // 已登记
        else {
            checkIn = peopleInfo.getPeopleStatus();
            // 计算人员年龄
            Integer age = Integer.valueOf(getAge(peopleInfo.getBirthday()));

            // 查询核查记录信息
            CheckRecordInfoVo checkRecordInfoVo = new CheckRecordInfoVo();
            checkRecordInfoVo.setRecordPeople(currentUser.getNickname());
            checkRecordInfoVo.setCheckTime(new Date());
            // 实名制登记
            checkRecordInfoVo.setCheckIn(checkIn);
            // 安全教育
            if (peopleInfo.getEduState() == null) {
                checkRecordInfoVo.setSafeEdu("0");
            } else {
                checkRecordInfoVo.setSafeEdu(peopleInfo.getEduState());
            }
            // 查询当前项目的配置信息
            QueryWrapper<WarningConfig> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("tenant_id_", query.getTenantId());
            WarningConfig warningConfig = warningConfigMapper.selectOne(queryWrapper);
            // 人员年龄
            if (peopleInfo.getGender().equals("1")) {
                if (warningConfig.getManAgeSwitch() == 1 && age > warningConfig.getManAge()) {
                    // 超龄
                    checkRecordInfoVo.setAge("1");
                } else {
                    // 未超龄
                    checkRecordInfoVo.setAge("0");
                }
            } else {
                if (warningConfig.getWomanAgeSwitch() == 1 && age > warningConfig.getWomanAge()) {
                    // 超龄
                    checkRecordInfoVo.setAge("1");
                } else {
                    // 未超龄
                    checkRecordInfoVo.setAge("0");
                }
            }

            // 人员出勤
            // 计算从上次出勤到目前为止，未出勤天数
            if (peopleInfo.getRecordTime() == null) {
                checkRecordInfoVo.setAttendance("1");
            }else {
                int days = Integer.valueOf(daysBetween(peopleInfo.getRecordTime(), new Date()));
                if (warningConfig.getAbsentSwitch() == 1 && days > warningConfig.getAbsent()) {
                    checkRecordInfoVo.setAttendance("1");
                } else {
                    checkRecordInfoVo.setAttendance("0");
                }
            }
            RecordDetailVo recordDetailVo = new RecordDetailVo();
            recordDetailVo.setPeopleInfoVo(peopleInfo);
            recordDetailVo.setCheckRecordInfoVo(checkRecordInfoVo);
            return RestBuilders.successBuilder().data(recordDetailVo).build();
        }
    }

    @Override
    public RestMessage getCheckRecordList(RequestModel<CheckRecordDTO> query) {
        IPage<CheckRecordVo> page = new Page(query.getPage().getCurrent(), query.getPage().getSize());
        //项目id 过滤
        if (null != linkappUserContextProducer.getCurrent()) {
            query.getCustomQueryParams().setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        }
        List<CheckRecordVo> checkRecordList = laborManagementMapper.getCheckRecordList(query.getCustomQueryParams(), page);
        page.setRecords(checkRecordList);
        return RestBuilders.successBuilder().data(page).build();
    }

    @Override
    public RestMessage saveCheckRecord(AppPeopleCheck dto) {
        //项目id 过滤
        if (null != linkappUserContextProducer.getCurrent()) {
            LinkappUser userInfo = linkappUserContextProducer.getNotNullCurrent();
            dto.setTenantId(userInfo.getTenantId());
            dto.setCreateTime(new Date());
            dto.setCreatorId(String.valueOf(userInfo.getId()));
            dto.setModifyTime(new Date());
            dto.setModifyId(String.valueOf(userInfo.getId()));
        }
        dto.setUpdateControlId(UUID.randomUUID().toString());
        // 无需处理
        if (dto.getDealRequire().equals("2")) {
            dto.setStatus("1");
        } else {
            dto.setStatus("0");
        }
        laborManagementMapper.insert(dto);
        return RestBuilders.successBuilder().message("保存成功").build();
    }

    @Override
    public RestMessage queryRecordDetail(String id) {
        AppPeopleCheck appPeopleCheck = laborManagementMapper.selectById(id);
        return RestBuilders.successBuilder().data(appPeopleCheck).build();
    }

    @Override
    public RestMessage deleteRecord(CheckRecordVo vo) {
        laborManagementMapper.deleteById(vo.getId());
        return RestBuilders.successBuilder().build();
    }

    /**
     * 查询当前状态
     * @param query
     * @return
     */
    @Override
    public RestMessage queryCurState(CheckPeopleInfoDTO query) {
        //项目id 过滤
        if (null != linkappUserContextProducer.getCurrent()) {
            query.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        }

        // 查询核查人员信息
        PeopleInfoVo peopleInfo = laborManagementMapper.getPeopleInfo(query);
        if (peopleInfo == null) {
            // 核查记录信息
            CheckRecordInfoVo checkRecordInfoVo = new CheckRecordInfoVo();
            return RestBuilders.successBuilder().data(checkRecordInfoVo).build();
        } else {
            String checkIn = peopleInfo.getPeopleStatus();
            // 计算人员年龄
            Integer age = Integer.valueOf(getAge(peopleInfo.getBirthday()));

            // 核查记录信息
            CheckRecordInfoVo checkRecordInfoVo = new CheckRecordInfoVo();
            // 实名制登记
            checkRecordInfoVo.setCheckIn(checkIn);
            // 安全教育
            checkRecordInfoVo.setSafeEdu(peopleInfo.getEduState());
            // 查询当前项目的配置信息
            QueryWrapper<WarningConfig> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("tenant_id_", query.getTenantId());
            WarningConfig warningConfig = warningConfigMapper.selectOne(queryWrapper);
            // 人员年龄
            if (peopleInfo.getGender().equals("1")) {
                if (warningConfig.getManAgeSwitch() == 1 && age > warningConfig.getManAge()) {
                    // 超龄
                    checkRecordInfoVo.setAge("1");
                } else {
                    // 未超龄
                    checkRecordInfoVo.setAge("0");
                }
            } else {
                if (warningConfig.getWomanAgeSwitch() == 1 && age > warningConfig.getWomanAge()) {
                    // 超龄
                    checkRecordInfoVo.setAge("1");
                } else {
                    // 未超龄
                    checkRecordInfoVo.setAge("0");
                }
            }

            // 人员出勤
            // 计算从上次出勤到目前为止，未出勤天数
            if (peopleInfo.getRecordTime() == null) {
                checkRecordInfoVo.setAttendance("1");
            } else {
                int days = Integer.valueOf(daysBetween(peopleInfo.getRecordTime(), new Date()));
                if (warningConfig.getAbsentSwitch() == 1 && days > warningConfig.getAbsent()) {
                    checkRecordInfoVo.setAttendance("1");
                } else {
                    checkRecordInfoVo.setAttendance("0");
                }
            }
            return RestBuilders.successBuilder().data(checkRecordInfoVo).build();
        }
    }

    @Override
    public RestMessage dealCheckRecord(AppPeopleCheck dto) {
        AppPeopleCheck appPeopleCheck = new AppPeopleCheck();
        //项目id 过滤
        if (null != linkappUserContextProducer.getCurrent()) {
            LinkappUser userInfo = linkappUserContextProducer.getNotNullCurrent();
            appPeopleCheck.setModifyTime(new Date());
            appPeopleCheck.setModifyId(String.valueOf(userInfo.getId()));
            appPeopleCheck.setDealName(userInfo.getNickname());
            appPeopleCheck.setDealTime(new Date());
        }
        appPeopleCheck.setDealResult(dto.getDealResult());
        appPeopleCheck.setStatus("1");
        appPeopleCheck.setUpdateControlId(UUID.randomUUID().toString());
        UpdateWrapper<AppPeopleCheck> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", dto.getId());
        wrapper.eq("update_control_id_", dto.getUpdateControlId());
        int update = laborManagementMapper.update(appPeopleCheck, wrapper);
        if (update == 1) {
            return RestBuilders.successBuilder().message("操作成功").build();
        } else {
            return RestBuilders.failureBuilder().message("操作失败，数据已被更新").build();
        }
    }

    @Override
    public RestMessage getCount(CheckRecordDTO dto) {
        LinkappUser userInfo = linkappUserContextProducer.getNotNullCurrent();
        dto.setTenantId(userInfo.getTenantId());
        CheckCountVo count = laborManagementMapper.getCount(dto);
        return RestBuilders.successBuilder().data(count).build();
    }

    /**
     * OCR识别身份证
     * @return
     * @throws Exception
     */
    @Override
    public RestMessage ocrIdentify(OCRIdentifyDTO dto) throws Exception {
        InputStream inputStream = base64ToInputStream(dto.getPicCode());
        Client client = createClient(accessKeyId, accessKeySecret, endpoint);
        RecognizeIdcardRequest recognizeIdcardRequest = new RecognizeIdcardRequest();
        RuntimeOptions runtime = new RuntimeOptions();
        recognizeIdcardRequest.setBody(inputStream);
        RecognizeIdcardResponse recognizeIdcardResponse = null;
        try {
            recognizeIdcardResponse = client.recognizeIdcardWithOptions(recognizeIdcardRequest, runtime);
        } catch (TeaException error) {
            // 如有需要，请打印 error
//            com.aliyun.teautil.Common.assertAsString(error.message);
            return RestBuilders.failureBuilder().message("请确认拍摄完整，保持光线充足").build();
        } catch (Exception _error) {
//            TeaException error = new TeaException(_error.getMessage(), _error);
//            // 如有需要，请打印 error
//            com.aliyun.teautil.Common.assertAsString(error.message);
            return RestBuilders.failureBuilder().message("请确认拍摄完整，保持光线充足").build();
        }
        String data = recognizeIdcardResponse.getBody().getData();
        JSONObject responseObject = JSONObject.parseObject(data).getJSONObject("data").getJSONObject("face").getJSONObject("data");
        String cardNo = responseObject.getString("idNumber");
        String name = responseObject.getString("name");
        CheckPeopleInfoDTO checkPeopleInfoDTO = new CheckPeopleInfoDTO();
        checkPeopleInfoDTO.setCardNo(cardNo);
        RestMessage restMessage = getPeopleInfo(checkPeopleInfoDTO);
        RecordDetailVo recordDetailVo = restMessage.getData();
        // 未登记，则使用OCR识别的人名
        if (recordDetailVo.getPeopleInfoVo().getUserName() == null) {
            recordDetailVo.getPeopleInfoVo().setUserName(name);
        }
        String restCode = restMessage.getCode();
        String restMsg = restMessage.getMessage();
        return RestBuilders.successBuilder().data(recordDetailVo).message(restMsg).code(restCode).build();
    }

    /**
    * @Description:
    * @Param: [query]
    * @return: site.morn.rest.RestMessage
    * @Author: 胡明威
    * @Date: 2023/8/14
    */
    @Override
    public RestMessage getPeopleList(CheckPeopleInfoDTO query) {
        LinkappUser currentUser = linkappUserContextProducer.getCurrent();
        //项目id 过滤
        if (null != currentUser) {
            query.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        }
        // 查询核查人员信息
        List<PeopleInfoVo> peopleList = laborManagementMapper.getPeopleList(query);
        return RestBuilders.successBuilder().data(peopleList).build();
    }

    public static int getAge(Date birthDay) {
        Calendar cal = Calendar.getInstance();
        if (cal.before(birthDay)) { //出生日期晚于当前时间，无法计算
            throw new IllegalArgumentException(
                    "The birthDay is before Now.It's unbelievable!");
        }
        int yearNow = cal.get(Calendar.YEAR);  //当前年份
        int monthNow = cal.get(Calendar.MONTH);  //当前月份
        int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH); //当前日期
        cal.setTime(birthDay);
        int yearBirth = cal.get(Calendar.YEAR);
        int monthBirth = cal.get(Calendar.MONTH);
        int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
        int age = yearNow - yearBirth;   //计算整岁数
        if (monthNow <= monthBirth) {
            if (monthNow == monthBirth) {
                if (dayOfMonthNow < dayOfMonthBirth) age--;//当前日期在生日之前，年龄减一
            }else{
                age--;//当前月份在生日之前，年龄减一
                 }
        } return age;
    }

    /**
     * JAVA计算两个日期相差多少天(by date)
     * @author humingwei
     */
    public static int daysBetween(Date date1,Date date2){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date1);
        long time1 = cal.getTimeInMillis();
        cal.setTime(date2);
        long time2 = cal.getTimeInMillis();
        long between_days=(time2-time1)/(1000*3600*24);
        return Integer.parseInt(String.valueOf(between_days));
    }

    /**
     * base64转InputStream
     * @param base64
     * @return
     */
    public static InputStream base64ToInputStream(String base64) {
        ByteArrayInputStream stream = null;
        try {
            byte[] bytes = Base64.getDecoder().decode(base64);
            stream = new ByteArrayInputStream(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return stream;
    }

    public static Client createClient(String accessKeyId, String accessKeySecret, String endpoint) throws Exception {
        Config config = new com.aliyun.teaopenapi.models.Config().setAccessKeyId(accessKeyId).setAccessKeySecret(accessKeySecret).setReadTimeout(10000).setConnectTimeout(10000);
        config.endpoint = endpoint;
        return new Client(config);
    }
}
